package com.mugui.spring.util;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;

import org.apache.catalina.core.ApplicationPart;
import org.apache.tomcat.util.http.fileupload.FileItem;
import org.apache.tomcat.util.http.fileupload.disk.DiskFileItem;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSONObject;
import com.mugui.spring.net.bean.NetBag;

import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Request.Builder;
import okhttp3.RequestBody;
import okhttp3.Response;

public class HTTPUtil {

	private static HashMap<String, OkHttpClient> map = new HashMap<>();

	/**
	 * 
	 * @auther 木鬼
	 * @param url 服务器
	 * @return
	 */
	public static Object get(String url) {
		return okHttp(RequestMethod.GET, url, null, null);
	}

	/**
	 * 
	 * @auther 木鬼
	 * @param url      服务器
	 * @param heandler heandler内容
	 * @return
	 */
	public static Object get(String url, Map<String, String> headler) {
		return okHttp(RequestMethod.GET, url, headler, null);
	}

	/**
	 * 
	 * @auther 木鬼
	 * @param url  转发服务器
	 * @param body body路径
	 * @return
	 */
	public static String post(String url) {
		return okHttp(RequestMethod.POST, url, null, null);
	}

	/**
	 * 
	 * @auther 木鬼
	 * @param url  转发服务器
	 * @param body body路径
	 * @return
	 */
	public static String post(String url, String body) {
		return okHttp(RequestMethod.POST, url, null, body);
	}

	/**
	 * 
	 * @auther 木鬼
	 * @param url      转发服务器
	 * @param heandler heandler内容
	 * @param body     body路径
	 * @return
	 */
	public static String post(String url, Map<String, String> headler, String body) {
		return okHttp(RequestMethod.POST, url, headler, body);
	}

	/**
	 * 
	 * @auther 木鬼
	 * @param url      转发服务器
	 * @param heandler heandler内容
	 * @param file     file路径
	 * @return
	 */
	public static String post(String url, Map<String, String> headler, JSONObject object, MultipartFile[] file) {
		return okHttpFile(url, headler, object, file);
	}

	public static String okHttp(RequestMethod method, String url, Map<String, String> headler, String body) {
		OkHttpClient httpClient = map.get(url);
		if (httpClient == null) {
			synchronized (map) {
				httpClient = map.get(url);
				if (httpClient == null) {
					httpClient = new OkHttpClient().newBuilder().connectTimeout(15, TimeUnit.SECONDS)
							.readTimeout(15, TimeUnit.SECONDS).build();
					map.put(url, httpClient);
				}
			}
		}
		InputStream inputStream = null;
		ByteArrayOutputStream outputStream = null;
		Response response = null;
		try {
			Builder request = getRequest(url, headler);
			if (method == RequestMethod.GET)
				response = httpClient.newCall(request.get().build()).execute();
			else if (method == RequestMethod.POST)
				response = httpClient.newCall(request
						.post(RequestBody.create(MediaType.parse("application/json;charset=UTF-8"), body)).build())
						.execute();
			if (response.code() == 200) {
				inputStream = response.body().byteStream();
				outputStream = new ByteArrayOutputStream();
				byte[] by = new byte[1024];
				int len = -1;
				while ((len = inputStream.read(by)) > -1) {
					outputStream.write(by, 0, len);
				}
				return outputStream.toString("UTF-8");
			}
			inputStream = response.body().byteStream();
			outputStream = new ByteArrayOutputStream();
			byte[] by = new byte[1024];
			int len = -1;
			while ((len = inputStream.read(by)) > -1) {
				outputStream.write(by, 0, len);
			}
			throw new RuntimeException(response.code() + "" + outputStream.toString("UTF-8"));
		} catch (Exception e) {
			throw new RuntimeException(method + ":" + url + "--" + body, e);
		} finally {
			try {
				if (outputStream != null)
					outputStream.close();
				if (inputStream != null)
					inputStream.close();
				if (response != null)
					response.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	private static String okHttpFile(String url, Map<String, String> headler, JSONObject object, MultipartFile[] file) {
		if (file == null || file.length == 0) {
			throw new RuntimeException("MultipartFile file 不能为空");
		}
		OkHttpClient httpClient = map.get(url);
		if (httpClient == null) {
			synchronized (map) {
				httpClient = map.get(url);
				if (httpClient == null) {
					httpClient = new OkHttpClient().newBuilder().connectTimeout(10, TimeUnit.SECONDS)
							.readTimeout(10, TimeUnit.SECONDS).build();
					map.put(url, httpClient);
				}
			}
		}
		InputStream inputStream = null;
		ByteArrayOutputStream outputStream = null;
		Response response = null;
		try {
			Builder request = getRequest(url, headler);
			MultipartBody.Builder builder = new MultipartBody.Builder();
			builder.setType(MultipartBody.FORM);
			{
				Iterator<Entry<String, Object>> iterator = object.entrySet().iterator();
				while (iterator.hasNext()) {
					Entry<String, Object> next = iterator.next();
					if (next.getValue() != null)
						builder.addFormDataPart(next.getKey(), next.getValue().toString());
				}
			}
			{
				Field declaredField = file[0].getClass().getDeclaredField("part");
				declaredField.setAccessible(true);
				Field declaredField2 = ApplicationPart.class.getDeclaredField("fileItem");
				declaredField2.setAccessible(true);
				for (int i = 0; i < file.length; i++) {
					ApplicationPart part = (ApplicationPart) declaredField.get(file[i]);
					DiskFileItem item = (DiskFileItem) declaredField2.get(part);
					builder.addFormDataPart(NetBag.STEALTH_UPLOAD_FILE, file[i].getOriginalFilename(),
							RequestBody.create(MediaType.parse(file[i].getContentType()), item.getStoreLocation()));
				}
			}

			response = httpClient.newCall(request.post(builder.build()).build()).execute();
			if (response.code() == 200) {
				inputStream = response.body().byteStream();
				outputStream = new ByteArrayOutputStream();
				byte[] by = new byte[1024];
				int len = -1;
				while ((len = inputStream.read(by)) > -1) {
					outputStream.write(by, 0, len);
				}
				return outputStream.toString("UTF-8");
			}
			inputStream = response.body().byteStream();
			outputStream = new ByteArrayOutputStream();
			byte[] by = new byte[1024];
			int len = -1;
			while ((len = inputStream.read(by)) > -1) {
				outputStream.write(by, 0, len);
			}
			throw new RuntimeException(response.code() + "" + outputStream.toString("UTF-8"));
		} catch (Exception e) {
			throw new RuntimeException("okHttpFile :" + url + "--", e);
		} finally {
			try {
				if (outputStream != null)
					outputStream.close();
				if (inputStream != null)
					inputStream.close();
				if (response != null)
					response.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	private static Builder getRequest(String url, Map<String, String> headler) {
		Builder builder = new Request.Builder().url(url);
		if (headler != null) {
			Iterator<Entry<String, String>> iterator = headler.entrySet().iterator();

			while (iterator.hasNext()) {
				Entry<String, String> next = iterator.next();
				builder = builder.addHeader(next.getKey().trim(), next.getValue().trim());
			}
		}
		return builder;
	}

}
